home *** CD-ROM | disk | FTP | other *** search
/ ETO Development Tools 4 / ETO Development Tools 4.iso / Tools - Objects / MacApp / MacApp 3.0a2 / Libraries / USynchScroller.cp < prev    next >
Encoding:
Text File  |  1991-05-01  |  12.3 KB  |  428 lines  |  [TEXT/MPS ]

  1. // USynchScroller.cp 
  2. // Copyright © 1989-1991 by Apple Computer Inc. All rights reserved.
  3.  
  4. #ifndef __UGEOMETRY__
  5. #include <UGeometry.h>
  6. #endif
  7.  
  8. #ifndef __ULIST__
  9. #include <UList.h>
  10. #endif
  11.  
  12. #ifndef __UEVENT__
  13. #include <UEvent.h>
  14. #endif
  15.  
  16. #ifndef __UCOMMAND__
  17. #include <UCommand.h>
  18. #endif
  19.  
  20. #ifndef __UDOCUMENT__
  21. #include <UDocument.h>
  22. #endif
  23.  
  24. #ifndef __UWINDOW__
  25. #include <UWindow.h>
  26. #endif
  27.  
  28. #ifndef __UFAILURE__
  29. #include <UFailure.h>
  30. #endif
  31.  
  32. #ifndef __UMACAPPUTILITIES__
  33. #include <UMacAppUtilities.h>
  34. #endif
  35.  
  36. #ifndef __DIALOGS__
  37. #include <Dialogs.h>
  38. #endif
  39.  
  40. #ifndef __UPATCH__
  41. #include <UPatch.h>
  42. #endif
  43.  
  44. #ifndef __UMACAPPGLOBALS__
  45. #include <UMacAppGlobals.h>
  46. #endif
  47.  
  48. #ifndef __STDLIB__
  49. #include "StdLib.h"
  50. #endif
  51.  
  52. #ifndef __UITERATOR__
  53. #include "UIterator.h"
  54. #endif
  55.  
  56. #ifndef __USYNCHSCROLLER__
  57. #include <USynchScroller.h>
  58. #endif
  59.  
  60. //--------------------------------------------------------------------------------------------------
  61. #pragma segment SyncScrollInit
  62.  
  63. pascal void InitUSynchScroller(void)
  64. {
  65.     if (qTemplateViews)
  66.     {
  67.         // Suppress Linker dead-stripping of these classes 
  68.         if (gDeadStripSuppression)
  69.         {
  70.             DontDeadStrip(TSynchScroller);
  71.             DontDeadStrip(TPrimaryScroller);
  72.             DontDeadStrip(TSecondaryScroller);
  73.         }
  74.     }
  75. }
  76.  
  77. //****************************************************************************************
  78. //  T S y n c h S c r o l l e r    
  79. //****************************************************************************************
  80.  
  81. //--------------------------------------------------------------------------------------------------
  82. #pragma segment SyncScrollRes
  83.  
  84. pascal void TSynchScroller::Initialize(void)    // override 
  85.  
  86. {
  87.     inherited::Initialize();
  88.     fLimiting = FALSE;
  89. }
  90.  
  91. //--------------------------------------------------------------------------------------------------
  92. #pragma segment SyncScrollRes
  93.  
  94. pascal void TSynchScroller::IRes(TDocument* itsDocument,
  95.                                  TView* itsSuperview,
  96.                                  Ptr& itsParams)// override 
  97. {
  98.     inherited::IRes(itsDocument, itsSuperview, itsParams);
  99. }
  100.  
  101. //--------------------------------------------------------------------------------------------------
  102. #pragma segment SyncScrollRes
  103.  
  104. pascal void TSynchScroller::SetScrollLimits(const VPoint& scrollLimit,
  105.                                             Boolean drawScrollBars)// override 
  106. {
  107.     Boolean wasLimiting = fLimiting;
  108.     FailInfo fi;
  109.  
  110.     VOLATILE(wasLimiting);
  111.  
  112.     fLimiting = TRUE;
  113.     if (fi.Try())
  114.     {
  115.         inherited::SetScrollLimits(scrollLimit, drawScrollBars);
  116.         fi.Success();
  117.     }
  118.     else    // Recover
  119.     {
  120.         fLimiting = wasLimiting;
  121.         fi.ReSignal();
  122.     }
  123.     fLimiting = wasLimiting;
  124. }
  125.  
  126. //--------------------------------------------------------------------------------------------------
  127. #pragma segment SyncScrollFields
  128.  
  129. pascal void TSynchScroller::Fields(TObject* obj)// override 
  130. {
  131.     obj->DoToField("TSynchScroller", (Ptr)NULL, bClass);
  132.     obj->DoToField("fLimiting", (Ptr) & fLimiting, bBoolean);
  133.     inherited::Fields(obj);
  134. }
  135.  
  136. //****************************************************************************************
  137. //  T P r i m a r y S c r o l l e r    
  138. //****************************************************************************************
  139. //--------------------------------------------------------------------------------------------------
  140. #pragma segment SyncScrollRes
  141.  
  142. pascal void TPrimaryScroller::Initialize(void)    // override 
  143. {
  144.     inherited::Initialize();
  145.     fSecondaryScrollers = NULL;
  146. }
  147.  
  148. //--------------------------------------------------------------------------------------------------
  149. #pragma segment SyncScrollRes
  150.  
  151. pascal void TPrimaryScroller::IRes(TDocument* itsDocument,
  152.                                    TView* itsSuperview,
  153.                                    Ptr& itsParams)// override 
  154. {
  155.     inherited::IRes(itsDocument, itsSuperview, itsParams);
  156. }
  157.  
  158. //--------------------------------------------------------------------------------------------------
  159. #pragma segment SyncScrollRes
  160.  
  161. pascal void TPrimaryScroller::Free(void)        // override 
  162.  
  163. {
  164.     fSecondaryScrollers = (TList *)FreeIfObject(fSecondaryScrollers);
  165.     inherited::Free();
  166. }
  167.  
  168. //--------------------------------------------------------------------------------------------------
  169. #pragma segment SyncScrollRes
  170.  
  171. pascal void TPrimaryScroller::AddSecondaryScroller(TSecondaryScroller* itsSecondaryScroller,
  172.                                                    VCoordinate itsHDependency,
  173.                                                    VCoordinate itsVDependency)
  174. {
  175.     if (itsSecondaryScroller)
  176.     {
  177.         // !!! Really should give notification by something like BeWithPrimaryScroller.
  178.         itsSecondaryScroller->fPrimaryScroller = this;
  179.         itsSecondaryScroller->fDeltaFactor = Point((short)itsVDependency, (short)itsHDependency);    // long coerced to short
  180.  
  181.         if (!fSecondaryScrollers)
  182.             fSecondaryScrollers = NewList();
  183.  
  184.         fSecondaryScrollers->Insert(itsSecondaryScroller);
  185.  
  186.     }
  187. }
  188.  
  189. //--------------------------------------------------------------------------------------------------
  190. #pragma segment SyncScrollRes
  191.  
  192. pascal void TPrimaryScroller::RemoveSecondaryScroller(TSecondaryScroller* itsSecondaryScroller)
  193. {
  194.     if (itsSecondaryScroller)
  195.     {
  196.         // !!! Really should give notification by something like BeInPrimaryScroller.
  197.         itsSecondaryScroller->fPrimaryScroller = NULL;
  198.         if (fSecondaryScrollers)
  199.         {
  200.             fSecondaryScrollers->Delete(itsSecondaryScroller);
  201.             // !!! TViews should be this nice with subview lists
  202.             if (fSecondaryScrollers->IsEmpty())
  203.                 fSecondaryScrollers = (TList *)FreeIfObject(fSecondaryScrollers);
  204.         }
  205.     }
  206. }
  207.  
  208. //--------------------------------------------------------------------------------------------------
  209. #pragma segment SyncScrollRes
  210.  
  211. pascal void TPrimaryScroller::DoScroll(const VPoint& delta,
  212.                                        Boolean redraw)// override 
  213. {
  214.  
  215.     // If invoked by SetScrollLimits, don't affect peer scrollers
  216.     if (!fLimiting)
  217.     {
  218.         CObjectIterator iter(fSecondaryScrollers);
  219.         TSecondaryScroller* aSecondaryScroller;
  220.     
  221.         for (aSecondaryScroller = (TSecondaryScroller*) iter.FirstObject(); iter.More(); aSecondaryScroller = (TSecondaryScroller*) iter.NextObject())
  222.         {
  223.             VPoint itsDelta(delta);
  224.         
  225.             for (VHSelect vhs = vSel; vhs <= hSel; ++vhs)
  226.                 if (aSecondaryScroller->fDeltaFactor[vhs])    // kVDependent or kHDependent 
  227.                 {
  228.                     if (itsDelta[vhs] < 0)
  229.                     {
  230.                         // !!!FIX the following 2 lines after MPW C compiler bug is corrected.
  231.                         long temp = Max(itsDelta[vhs], -aSecondaryScroller->fTranslation[vhs]);
  232.                         itsDelta[vhs] = temp;
  233.                     }
  234.                     else if (itsDelta[vhs] > 0)
  235.                     {
  236.                         // !!!FIX the following 2 lines after MPW C compiler bug is corrected.
  237.                         long temp1 = Min(itsDelta[vhs], aSecondaryScroller->fMaxTranslation[vhs] - aSecondaryScroller->fTranslation[vhs]);
  238.                         itsDelta[vhs] = temp1;
  239.                     }
  240.                     aSecondaryScroller->fTranslation[vhs] += itsDelta[vhs];
  241.                 }
  242.         
  243.             if (itsDelta != gZeroVPt)
  244.             {
  245.                 aSecondaryScroller->InvalidateFocus();    // You never know who might call 
  246.                 aSecondaryScroller->UpdateCoordinates();
  247.             }
  248.         }
  249.     }
  250.  
  251.     inherited::DoScroll(delta, redraw);
  252. }
  253.  
  254. //--------------------------------------------------------------------------------------------------
  255. #pragma segment SyncScrollRes
  256.  
  257. pascal void TPrimaryScroller::ScrollDraw(const VPoint& delta,
  258.                                          Boolean invalidate)// override 
  259. {
  260.     if (fSuperView->IsDrawable())
  261.     {
  262.         Rect superVisRect;
  263.         VRect myVFrame;
  264.         Rect myQDFrame;
  265.         RgnHandle scrollRgn;
  266.         FailInfo fi;
  267.         
  268.         VOLATILE(scrollRgn);
  269.  
  270.         if (fi.Try())
  271.         {
  272.             scrollRgn = MakeNewRgn();
  273.     
  274.             this->GetFrame(myVFrame);
  275.             fSuperView->ViewToQDRect(myVFrame, myQDFrame);
  276.             RectRgn(scrollRgn, myQDFrame);
  277.     
  278.             fSuperView->GetDrawableQDRect(superVisRect);
  279.     
  280.             if (gIntenseDebugging)
  281.                 WriteFocus();
  282.     
  283.             // Too far to use ScrollRect
  284.             if ((labs(delta.h) > kMaxCoord) || (labs(delta.v) > kMaxCoord))
  285.             {
  286.                 this->ForceRedraw();
  287.  
  288.                 CObjectIterator iter(fSecondaryScrollers);
  289.                 TSecondaryScroller* aScroller;
  290.             
  291.                 for (aScroller = (TSecondaryScroller*) iter.FirstObject(); iter.More(); aScroller = (TSecondaryScroller*) iter.NextObject())
  292.                 {
  293.                     if (delta.v && (aScroller->fDeltaFactor.v == kVDependent))
  294.                         aScroller->ForceRedraw();
  295.                     else if (delta.h && (aScroller->fDeltaFactor.h == kHDependent))
  296.                         aScroller->ForceRedraw();
  297.                 }
  298.             }
  299.             else        // Can use ScrollRect
  300.             {
  301.     #if qDebug
  302.                 UseTempRgn2("TPrimaryScroller.ScrollDraw");
  303.     #endif
  304.                 if (qDebug)
  305.                     fSuperView->AssumeFocused();
  306.     
  307.                 CObjectIterator iter(fSecondaryScrollers);
  308.                 TSecondaryScroller* aScroller;
  309.             
  310.                 for (aScroller = (TSecondaryScroller*) iter.FirstObject(); iter.More(); aScroller = (TSecondaryScroller*) iter.NextObject())
  311.                 {
  312.                     VRect frameVRect;
  313.                     Rect frameRect;
  314.                     Point localDeltaFactor = aScroller->fDeltaFactor;
  315.                 
  316.                     // !!! with additional tests we could also support scrollers in other superviews
  317.                     // and non-matching extents and scrollLimits in the pertinent axis by simply calling
  318.                     // their scrolling methods.  This would be nice for synchronized windows.
  319.                     aScroller->GetFrame(frameVRect);
  320.                     aScroller->fSuperView->ViewToQDRect(frameVRect, frameRect);
  321.                     // main scroller is moving both directions but dependent can only move in v
  322.                     if (delta.h && delta.v && (localDeltaFactor.h == kNotHDependent) && (localDeltaFactor.v == kVDependent))
  323.                     {
  324.                         ScrollRect(frameRect, 0, (short) - delta.v, gTempRgn2);
  325.                         aScroller->fSuperView->InvalidateRgn(gTempRgn2);
  326.                     }
  327.                     // main scroller is moving both directions but dependent can only move in h
  328.                     else if (delta.h && delta.v && (localDeltaFactor.h == kHDependent) && (localDeltaFactor.v == kNotVDependent))
  329.                     {
  330.                         ScrollRect(frameRect, (short) - delta.h, 0, gTempRgn2);
  331.                         aScroller->fSuperView->InvalidateRgn(gTempRgn2);
  332.                     }
  333.                     // main scroller is moving in either direction and dependent can follow
  334.                     else if ((delta.h && (localDeltaFactor.h == kHDependent)) || (delta.v && (localDeltaFactor.v == kVDependent)))
  335.                     {
  336.                         RectRgn(gTempRgn2, frameRect);
  337.                         UnionRgn(scrollRgn, gTempRgn2, scrollRgn);
  338.                     }
  339.                 }
  340.  
  341.                 if (qDebug)
  342.                     fSuperView->AssumeFocused();
  343.     
  344.                 // Now, we've either scrolled any dependent scrollers that can't scroll with
  345.                 // us or we've accumulated their frames in scrollRgn.  By clipping to the
  346.                 // accumulated region we can just scroll the entire superview and the right
  347.                 // stuff should happen. (Cross fingers)
  348.                 SectRgn(scrollRgn, qd.thePort->clipRgn, scrollRgn);
  349.     
  350.                 // Get clip so we can restore it later and keep from having
  351.                 // to invalidate the superview's focus
  352.                 GetClip(gTempRgn2);
  353.     
  354.                 SetClip(scrollRgn);
  355.                 ScrollRect(superVisRect, (short) - delta.h, (short) - delta.v, scrollRgn);
  356.     
  357.                 // restore the clip so we don't have to invalidate the focus
  358.                 SetClip(gTempRgn2);
  359.     
  360.                 fSuperView->InvalidateRgn(scrollRgn);
  361. #if qDebug
  362.                 DoneWithTempRgn2();
  363. #endif
  364.             }
  365.             scrollRgn = DisposeIfRgnHandle(scrollRgn);
  366.             fi.Success();
  367.         }
  368.         else    // Recover
  369.         {
  370.             scrollRgn = DisposeIfRgnHandle(scrollRgn);
  371.             fi.ReSignal();
  372.         }
  373.         if (!invalidate)
  374.             fSuperView->Update();
  375.     }
  376. }
  377. //--------------------------------------------------------------------------------------------------
  378. #pragma segment SyncScrollFields
  379.  
  380. pascal void TPrimaryScroller::Fields(TObject* obj)// override 
  381. {
  382.     obj->DoToField("TPrimaryScroller", (Ptr)NULL, bClass);
  383.     obj->DoToField("fSecondaryScrollers", (Ptr) & fSecondaryScrollers, bObject);
  384.     inherited::Fields(obj);
  385. }
  386.  
  387. //****************************************************************************************
  388. //  T S e c o n d a r y S c r o l l e r    
  389. //****************************************************************************************
  390.  
  391. //--------------------------------------------------------------------------------------------------
  392. #pragma segment SyncScrollRes
  393.  
  394. pascal void TSecondaryScroller::Initialize(void)// override 
  395.  
  396. {
  397.     inherited::Initialize();
  398.     fPrimaryScroller = NULL;
  399.     fDeltaFactor.h = kNotHDependent;
  400.     fDeltaFactor.v = kNotVDependent;
  401. }
  402.  
  403. //--------------------------------------------------------------------------------------------------
  404. #pragma segment SyncScrollRes
  405.  
  406. pascal void TSecondaryScroller::DoScroll(const VPoint& delta,
  407.                                          Boolean redraw)// override 
  408. {
  409.     // Invoked by SetScrollLimits, so don't affect peer scrollers
  410.     if (fLimiting)
  411.         inherited::DoScroll(delta, redraw);
  412.     else
  413.         fPrimaryScroller->ScrollBy(VPoint(fDeltaFactor.v * delta.v, fDeltaFactor.h * delta.h), redraw);
  414. }
  415.  
  416. //--------------------------------------------------------------------------------------------------
  417. #pragma segment SyncScrollFields
  418.  
  419. pascal void TSecondaryScroller::Fields(TObject* obj)// override 
  420. {
  421.     obj->DoToField("TSecondaryScroller", (Ptr)NULL, bClass);
  422.     obj->DoToField("fPrimaryScroller", (Ptr) & fPrimaryScroller, bObject);
  423.     obj->DoToField("fDeltaFactor", (Ptr) & fDeltaFactor, bPoint);
  424.     inherited::Fields(obj);
  425. }
  426.  
  427.  
  428.